using UnityEngine;

namespace Com.LuisPedroFonseca.ProCamera2D
{
	public class ProCamera2DPanAndZoom : BasePC2D, ISizeDeltaChanger, IPreMover
	{
		public static string ExtensionName = "Pan And Zoom";

		public bool AllowZoom = true;

		public float MouseZoomSpeed = 10f;

		public float PinchZoomSpeed = 50f;

		[Range(0f, 2f)]
		public float ZoomSmoothness = 0.2f;

		public float MaxZoomInAmount = 2f;

		public float MaxZoomOutAmount = 2f;

		public bool ZoomToInputCenter = true;

		private float _zoomAmount;

		private float _initialCamSize;

		private bool _zoomStarted;

		private float _origFollowSmoothnessX;

		private float _origFollowSmoothnessY;

		private float _prevZoomAmount;

		private float _zoomVelocity;

		private Vector3 _zoomPoint;

		private float _touchZoomTime;

		public bool AllowPan = true;

		public bool UsePanByDrag = true;

		[Range(0f, 1f)]
		public float StopSpeedOnDragStart = 0.95f;

		public Rect DraggableAreaRect = new Rect(0f, 0f, 1f, 1f);

		public Vector2 DragPanSpeed = new Vector2(80f, 80f);

		public bool UsePanByMoveToEdges;

		public Vector2 EdgesPanSpeed = new Vector2(2f, 2f);

		[Range(0f, 0.99f)]
		public float HorizontalPanEdges = 0.9f;

		[Range(0f, 0.99f)]
		public float VerticalPanEdges = 0.9f;

		private Vector2 _panDelta;

		private Transform _panTarget;

		private Vector2 _prevMousePosition;

		private int _prmOrder;

		private int _sdcOrder;

		public int PrMOrder
		{
			get
			{
				return _prmOrder;
			}
			set
			{
				_prmOrder = value;
			}
		}

		public int SDCOrder
		{
			get
			{
				return _sdcOrder;
			}
			set
			{
				_sdcOrder = value;
			}
		}

		protected override void Awake()
		{
			base.Awake();
			UpdateCurrentFollowSmoothness();
			_panTarget = new GameObject("PC2DPanTarget").transform;
			ProCamera2D.AddPreMover(this);
			ProCamera2D.AddSizeDeltaChanger(this);
		}

		private void Start()
		{
			_initialCamSize = ProCamera2D.ScreenSizeInWorldCoordinates.y * 0.5f;
		}

		protected override void OnEnable()
		{
			base.OnEnable();
			CenterPanTargetOnCamera(1f);
			ProCamera2D.Instance.AddCameraTarget(_panTarget);
		}

		protected override void OnDisable()
		{
			base.OnDisable();
			ProCamera2D.RemoveCameraTarget(_panTarget);
		}

		public void PreMove(float deltaTime)
		{
			if (base.enabled && AllowPan)
			{
				Pan(deltaTime);
			}
		}

		public float AdjustSize(float deltaTime, float originalDelta)
		{
			if (base.enabled && AllowZoom)
			{
				return Zoom(deltaTime) + originalDelta;
			}
			return originalDelta;
		}

		private void Pan(float deltaTime)
		{
			_panDelta = Vector2.zero;
			if (Time.time - _touchZoomTime < 0.1f)
			{
				return;
			}
			if (UnityEngine.Input.touchCount == 1 && UnityEngine.Input.GetTouch(0).phase == TouchPhase.Began)
			{
				CenterPanTargetOnCamera(StopSpeedOnDragStart);
			}
			Vector2 vector = Vector2.zero;
			for (int i = 0; i < UnityEngine.Input.touchCount; i++)
			{
				vector += -Input.GetTouch(i).deltaPosition;
			}
			if (UnityEngine.Input.touchCount == 1)
			{
				Vector2 normalizedInput = new Vector2(UnityEngine.Input.GetTouch(0).position.x / (float)Screen.width, UnityEngine.Input.GetTouch(0).position.y / (float)Screen.height);
				if (InsideDraggableArea(normalizedInput))
				{
					_panDelta = new Vector2(vector.x / (float)Screen.width, vector.y / (float)Screen.height);
				}
			}
			Vector2 dragPanSpeed = DragPanSpeed;
			if (_panDelta != Vector2.zero)
			{
				_panTarget.Translate(VectorHV(_panDelta.x * dragPanSpeed.x * ProCamera2D.ScreenSizeInWorldCoordinates.x, _panDelta.y * dragPanSpeed.y * ProCamera2D.ScreenSizeInWorldCoordinates.y) * deltaTime);
			}
			if ((ProCamera2D.IsCameraPositionLeftBounded && Vector3H(_panTarget.position) < Vector3H(ProCamera2D.LocalPosition)) || (ProCamera2D.IsCameraPositionRightBounded && Vector3H(_panTarget.position) > Vector3H(ProCamera2D.LocalPosition)))
			{
				_panTarget.position = VectorHVD(Vector3H(ProCamera2D.LocalPosition), Vector3V(_panTarget.position), Vector3D(_panTarget.position));
			}
			if ((ProCamera2D.IsCameraPositionBottomBounded && Vector3V(_panTarget.position) < Vector3V(ProCamera2D.LocalPosition)) || (ProCamera2D.IsCameraPositionTopBounded && Vector3V(_panTarget.position) > Vector3V(ProCamera2D.LocalPosition)))
			{
				_panTarget.position = VectorHVD(Vector3H(_panTarget.position), Vector3V(ProCamera2D.LocalPosition), Vector3D(_panTarget.position));
			}
		}

		private float Zoom(float deltaTime)
		{
			if (_panDelta != Vector2.zero)
			{
				CancelZoom();
				RestoreFollowSmoothness();
				return 0f;
			}
			float num = 0f;
			if (UnityEngine.Input.touchCount == 2)
			{
				Touch touch = UnityEngine.Input.GetTouch(0);
				Touch touch2 = UnityEngine.Input.GetTouch(1);
				Vector2 a = touch.position - new Vector2(touch.deltaPosition.x / (float)Screen.width, touch.deltaPosition.y / (float)Screen.height);
				Vector2 b = touch2.position - new Vector2(touch2.deltaPosition.x / (float)Screen.width, touch2.deltaPosition.y / (float)Screen.height);
				float magnitude = (a - b).magnitude;
				float magnitude2 = (touch.position - touch2.position).magnitude;
				num = magnitude - magnitude2;
				Vector2 vector = (touch.position + touch2.position) * 0.5f;
				_zoomPoint = VectorHVD(vector.x, vector.y, Mathf.Abs(ProCamera2D.CameraDepthPos));
				if (!_zoomStarted)
				{
					_zoomStarted = true;
					_panTarget.position = ProCamera2D.LocalPosition;
					UpdateCurrentFollowSmoothness();
					RemoveFollowSmoothness();
				}
				_touchZoomTime = Time.time;
			}
			else if (_zoomStarted && Mathf.Abs(_zoomAmount) < 0.001f)
			{
				RestoreFollowSmoothness();
				_zoomStarted = false;
			}
			float num2 = 0f;
			num2 = PinchZoomSpeed * 10f;
			_zoomAmount = Mathf.SmoothDamp(_prevZoomAmount, num * num2 * deltaTime, ref _zoomVelocity, ZoomSmoothness);
			float num3 = ProCamera2D.ScreenSizeInWorldCoordinates.y / 2f + _zoomAmount;
			float num4 = _initialCamSize / MaxZoomInAmount;
			float num5 = MaxZoomOutAmount * _initialCamSize;
			if (num3 < num4)
			{
				_zoomAmount -= num3 - num4;
			}
			else if (num3 > num5)
			{
				_zoomAmount -= num3 - num5;
			}
			_prevZoomAmount = _zoomAmount;
			if (ZoomToInputCenter)
			{
				float d = _zoomAmount / (ProCamera2D.ScreenSizeInWorldCoordinates.y / 2f);
				_panTarget.position += (_panTarget.position - ProCamera2D.GameCamera.ScreenToWorldPoint(_zoomPoint)) * d;
			}
			return _zoomAmount;
		}

		public void UpdateCurrentFollowSmoothness()
		{
			_origFollowSmoothnessX = ProCamera2D.HorizontalFollowSmoothness;
			_origFollowSmoothnessY = ProCamera2D.VerticalFollowSmoothness;
		}

		private void CenterPanTargetOnCamera(float interpolant)
		{
			if (_panTarget != null)
			{
				_panTarget.position = Vector3.Lerp(_panTarget.position, VectorHV(Vector3H(ProCamera2D.LocalPosition), Vector3V(ProCamera2D.LocalPosition)), interpolant);
			}
		}

		private void CancelZoom()
		{
			_zoomAmount = 0f;
			_prevZoomAmount = 0f;
			_zoomVelocity = 0f;
		}

		private void RestoreFollowSmoothness()
		{
			ProCamera2D.HorizontalFollowSmoothness = _origFollowSmoothnessX;
			ProCamera2D.VerticalFollowSmoothness = _origFollowSmoothnessY;
		}

		private void RemoveFollowSmoothness()
		{
			ProCamera2D.HorizontalFollowSmoothness = 0f;
			ProCamera2D.VerticalFollowSmoothness = 0f;
		}

		private bool InsideDraggableArea(Vector2 normalizedInput)
		{
			if (DraggableAreaRect.x == 0f && DraggableAreaRect.y == 0f && DraggableAreaRect.width == 1f && DraggableAreaRect.height == 1f)
			{
				return true;
			}
			if (normalizedInput.x > DraggableAreaRect.x + (1f - DraggableAreaRect.width) / 2f && normalizedInput.x < DraggableAreaRect.x + DraggableAreaRect.width + (1f - DraggableAreaRect.width) / 2f && normalizedInput.y > DraggableAreaRect.y + (1f - DraggableAreaRect.height) / 2f && normalizedInput.y < DraggableAreaRect.y + DraggableAreaRect.height + (1f - DraggableAreaRect.height) / 2f)
			{
				return true;
			}
			return false;
		}
	}
}
